<template>
  <div class="text-center">
    <q-scroll-area style="height: 600px; max-width: 800px;">
      <div
        class="my-canvas-container"
        :style="{
            backgroundColor: store.canvas.backgroundColor,
            backgroundImage: `url(${store.canvas.backgroundImage})`
        }"
      >
        <template v-for="(component) in store.components" :key="component.sid">
          <div
            class="my-component-container"
            :style="{
              left: component.position.x + 'px',
              top: component.position.y + 'px',
              width: component.position.w + 'px',
              height: component.position.h + 'px',
              zIndex: component.shape.zIndex,
              transform: component.shape.transform? `rotate(${component.shape.transform}deg)`:'rotate(0deg)',
            }"
          >
            <component
              :is="parseView(component)"
              :detail="component"
              :dynamic-data="varTbl"
              :current-switch="true"
              :motion-type-arr="motionTypeList"
              :event-type-arr="eventTypeList"
              :operator-type-arr="operatorTypeList"
              :operation-type-arr="eventOperationTypeList"
              @update-event="updateEvent"
            />
          </div>
        </template>
      </div>
      <ShowMsgDlg ref="myMsgDlgRef" :message="myEventMsg"/>
    </q-scroll-area>
  </div>
</template>

<script lang="ts">

import { defineComponent, nextTick, onMounted, onUnmounted, ref } from 'vue';
import Vue3DraggableResizable, { DraggableContainer } from 'vue3-draggable-resizable'
import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css'
import { parseViewName } from '../../hook/common/useComponentParse';
import { CEventMsgItem, CGraphEntity, EnumEditorEvent } from 'stores/editorModels';
import { useEditorExecPageComponents } from 'src/hook/editor/useEditorExecPageComponents';
import { useEditorStore } from 'stores/editorStore';
import { storeToRefs } from 'pinia';
import BaseComponent from 'components/views/BaseComponent.vue';
import { useRoute } from 'vue-router';
import { useCommonStore } from 'stores/commonStore';
import { EnumWSCommand, useScadaPacket } from 'src/hook/editor/useScadaPacket';
import { useMessageNotify } from 'src/hook/common/useMessageNotify';
import { EnumWebsocketState, socket } from 'src/socket/websocket';
import { useUivCatalogTbl } from 'src/hook/editor/useUivCatalogTbl';
import { uivCatalogType } from 'src/util/UivBaseConst';
import Timeout = NodeJS.Timeout;
import { EnumEventOperationType } from 'src/util/SelectBoxOption';
import ShowMsgDlg from 'pages/preview/ShowMsgDlg.vue';

export type ShowMsgDlgInstance = InstanceType<typeof ShowMsgDlg>;


export default defineComponent({
  name: 'ViewItem',
  extends: BaseComponent,
  components: {
    Vue3DraggableResizable,
    DraggableContainer,
    ShowMsgDlg
  },
  setup (props, context) {
    //*********************************************************
    //          route
    //*********************************************************
    //router是全局路由对象，route是当前路由对象
    let curRoute = useRoute();

    //*********************************************************
    //          store
    //*********************************************************
    //组件store
    const store = useEditorStore();
    const {
      components,
      componentState
    } = storeToRefs(store);

    //数据库store
    const commonStore = useCommonStore();
    const {
      application,
      user,
      varTbl
    } = storeToRefs(commonStore);

    //*********************************************************
    // 实现拖拽生成组件、保存组件、删除组件、更新页面组件
    //*********************************************************
    const {
      registerRecvComponentCB,
      getCurrentPageInfo
    } = useEditorExecPageComponents();

    //*********************************************************
    // 消息通知
    //*********************************************************
    //消息通知
    const {
      showMessage
    } = useMessageNotify();

    //*********************************************************
    // 消息通知
    //*********************************************************
    const {
      operatorTypeList,
      eventOperationTypeList,
      eventTypeList,
      motionTypeList,
      getUivCatalog,
      removeUivCatalog
    } = useUivCatalogTbl();

    //*********************************************************
    // 应用信息
    //*********************************************************
    //播放窗口
    let myMsgDlgRef = ref<ShowMsgDlgInstance|null>(null);
    let myEventMsg = ref<CEventMsgItem>({
      operationType: '',
      url: '',
      msg: ''
    });

    //测试事件
    const onClick = () => {
      alert('父节点单击！');
    }

    //测试事件
    const testEvent = () => {
      let msg: CEventMsgItem = {
        operationType: EnumEventOperationType.OPERATION_OPEN_URL,
        url: 'https://www.baidu.com',
        msg: ''
      }

      updateEvent(msg);
    }

    //更新
    const updateEvent = (msg: CEventMsgItem) => {
      switch (msg.operationType) {
        case EnumEventOperationType.OPERATION_OPEN_URL:
          window.open(msg.url, '_blank');
          break;
        case EnumEventOperationType.OPERATION_PLAY_VIDEO:
          if (myMsgDlgRef.value) {
            myEventMsg.value.operationType = msg.operationType;
            myEventMsg.value.url = msg.url;
            myEventMsg.value.msg = msg.msg;
            myMsgDlgRef.value.show('播放视频');
          }
          break;
        case EnumEventOperationType.OPERATION_PLAY_AUDIO:
          if (myMsgDlgRef.value) {
            myEventMsg.value.operationType = msg.operationType;
            myEventMsg.value.url = msg.url;
            myEventMsg.value.msg = msg.msg;
            myMsgDlgRef.value.show('播放音频');
          }
          break;
        case EnumEventOperationType.OPERATION_SEND_CHAT:
          break;
        case EnumEventOperationType.OPERATION_SEND_EMAIL:
          break;
      }
    }

    //*********************************************************
    // 变量表
    //*********************************************************
    //连接状态
    let wsConnected = ref(false);
    let wsTimer: Timeout;

    //socket通信函数
    const {
      WS_FRAME_HEADER,
      wsCertifyUser,
      wsRegisterVariable,
      wsReadVariable
    } = useScadaPacket();

    //web socket连接成功
    const onWebsocketConnected = () => {
      //连接状态
      wsConnected.value = true;

      //提示
      showMessage('Websocket服务器连接成功！');

      //认证
      wsCertifyUser(socket, user.value.username,
        user.value.password, application.value.projectId);
    }

    //web socket接收函数，msg为ArrayBuffer
    const onWebsocketReceived = (msg: any) => {
      //连接状态
      wsConnected.value = true;

      //二进制ArrayBuffer类型接收数据
      let len = msg.byteLength;
      let uint8Arr = new Uint8Array(msg);

      //解析
      let vid = 0, vdata = 0, status = 0;
      let ofs = 0;
      let header = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
      let command = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
      let size = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];

      //帧格式判断
      if ((header !== WS_FRAME_HEADER) || (len !== size + 6)) {
        console.log('数据帧格式不正确！');
        return;
      }

      //帧解析
      switch (command) {
        case EnumWSCommand.WS_CERTIFY_USER:
          if (size === 2) {
            status = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            if (status === 1) {
              wsRegisterVariable(socket, varTbl.value);
            }
          }
          break;
        case EnumWSCommand.WS_REGISTER_VARIABLE:
          if (size === 2) {
            status = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
            if (status === 1) {
              wsReadVariable(socket, varTbl.value);
            }
          }
          break;
        case EnumWSCommand.WS_READ_VARIABLE:
          if (size % 6 === 0) {
            let num = size % 6;
            for (let i = 0; i < num; i++) {
              vid = (uint8Arr[ofs++] << 24) | (uint8Arr[ofs++] << 16) | (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
              vdata = (uint8Arr[ofs++] << 8) | uint8Arr[ofs++];
              commonStore.addVariableTbl(vid, vdata);
            }
          }
          break;
        default:
          break;
      }
    }

    //关闭
    const onWebsocketClosed = () => {
      wsConnected.value = false;
    }

    //开启websocket
    const connectWebsocketServer = () => {
      //设置websocket通信信息
      //socket.connectURL = 'ws://' + canvas.value.wsAddr + ':' + canvas.value.wsPort;

      //初始化
      socket.init(onWebsocketReceived, onWebsocketConnected, onWebsocketClosed);

      //开始连接
      socket.connect('ws://127.0.0.1:6678');
    }

    //关闭websocket
    const closeWebsocket = () => {
      socket.close();
      wsConnected.value = false;
    }

    //*********************************************************
    //          动态组件解析
    //*********************************************************
    // 依据名称解析成vue组件
    const parseView = (com: CGraphEntity) => {
      return parseViewName(com);
    };


    //*********************************************************
    //          初始化
    //*********************************************************
    //初始化
    const initComponents = () => {
      //数据库清空
      commonStore.initVariableTbl();

      //注册收到一个组件数据后回调函数,创建变量数据库
      registerRecvComponentCB(createCurrentPageVariableTbl);

      //页面类型信息，空，模板、新建、已存在
      if ((curRoute.query.pageType) && (curRoute.query.pageId)) {
        let pageType = parseInt(curRoute.query.pageType as string);
        let id = parseInt(curRoute.query.pageId as string);
        if ((!isNaN(pageType)) && (!isNaN(id))) {
          store.setPage(pageType, id);

          //从数据库中加载本页面组件
          getCurrentPageInfo();
        }
      }
    }

    //*********************************************************
    //          启动
    //*********************************************************
    //从页面组件树中，创建当前页面变量表
    const createCurrentPageVariableTbl = () => {
      //创建变量数据库
      components.value.forEach((item) => {
        item.dataItem.forEach((el) => {
          //组件对应的数据节点
          commonStore.addVariableTbl(el.variableValue, 0);
        });
      });
    }

    //组件挂载
    onMounted(() => {
      //读取cataItem
      getUivCatalog(uivCatalogType.COMPARE_OPERATOR_TYPE_CODE);
      getUivCatalog(uivCatalogType.EVENT_OPERATION_TYPE_CODE);
      getUivCatalog(uivCatalogType.EVENT_TYPE_CODE);
      getUivCatalog(uivCatalogType.MOTION_TYPE_CODE);

      //读取user
      commonStore.getUser();

      //初始化组件表，数据表
      initComponents();

      //延时连接websocket
      nextTick(() => {
        connectWebsocketServer();
        //testEvent();
      });

      //创建websocket连接检查定时器,60s
      wsTimer = setInterval(() => {
        let status = socket.getStatus();
        console.log('Websocket Status:' + status);
        if ((!wsConnected.value) || (status === EnumWebsocketState.WS_CLOSED)) {
          connectWebsocketServer();
        }
      }, 60000);
    });

    //组件卸载
    onUnmounted(() => {
      //cataItem
      removeUivCatalog(uivCatalogType.COMPARE_OPERATOR_TYPE_CODE);
      removeUivCatalog(uivCatalogType.EVENT_OPERATION_TYPE_CODE);
      removeUivCatalog(uivCatalogType.EVENT_TYPE_CODE);
      removeUivCatalog(uivCatalogType.MOTION_TYPE_CODE);

      //store清空
      store.initCanvas();
      store.initComponents();
      commonStore.initVariableTbl();

      //关闭websocket
      closeWebsocket();

      //清除定时器
      clearInterval(wsTimer);
    })

    return {
      store,
      components,
      componentState,
      varTbl,

      operatorTypeList,
      eventOperationTypeList,
      eventTypeList,
      motionTypeList,

      myMsgDlgRef,
      myEventMsg,

      onClick,
      parseView,
      updateEvent,

      EnumEditorEvent
    };
  }
});

</script>

<style lang="scss" scoped>
.my-canvas-container {
  background-color: white;
  margin: 1px;
  padding: 2px;
  width: 100%;
  height: calc(100vh - 50px);
  position: relative;

  .my-component-container {
    position: absolute;
    display:inline-block;
  }
}
</style>
